﻿using ConsoleApp.Test;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Xml.Linq;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Log;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.ZLog;

namespace ConsoleApp
{
    unsafe internal class Program
    {
        static void Main(string[] args)
        {
            //FileStream stream = null;
            //byte[] buffer = new byte[10];
            //stream.Read(buffer);

            InitLog();

            int value = 10;
            int value2 = Interlocked.Decrement(ref value);

            int value3 = Interlocked.Increment(ref value);

            int value4 = Interlocked.Exchange(ref value, 20);


            TestLog();
            //TestSecurity.Test();

            //Com();
            //Dec();




            //string path = PathEx.ExecutablePath;
            //Console.WriteLine(path);

            //byte leftValue = 40;
            //byte rightValue = 34;
            //var ret1 = leftValue.CompareTo(rightValue);//6
            //var ret2 = rightValue.CompareTo(leftValue);//-6

            //int leftValue2 = 40;
            //int rightValue2 = 34;
            //var ret3 = leftValue2.CompareTo(rightValue2);//1
            //var ret4 = rightValue2.CompareTo(leftValue2);//-1

            ////Microsoft.EntityFrameworkCore, Version=8.0.11.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
            //string str = @"Microsoft.EntityFrameworkCore, Version=8.0.11.0, Culture=neutral, PublicKeyToken=adb9793829ddae60";
            //AssemblyName name = new AssemblyName(str);

            //Socket socket = null;
            //byte[] buffer = new byte[65536];
            //IAsyncResult asyncResult = socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ret => { }), 111);
            //int rcvLen = socket.EndReceive(asyncResult);
            //socket.Close();

            //TestConcurrentBag();
            //TestDateTime.Test();
            //TestArrayEx.Test();
            //TestObjectEx.Test();
            //TestObjectPool.Test();
            //TestAppConfigurationManager.Test();

            //Array array = new string[0];
            //array.GetLowerBound(0);

            //TestUnmanagedMemoryPointer.Test();
            //TestSpan.Test();
            //TestNativeMemory.Test();
            //TestNormalizer.Test();
            //TestNetTcpClient.Test();

            ////TestCode1();
            //BigInteger bigInteger = 123;
            //var v = bigInteger >> 1;

            //Tcp();
            Console.ReadKey();
        }


        private static void Com()
        {
            string[] files = Directory.GetFiles(@"E:\temp\dic");
            using (var fs = new MemoryStream())
            {
                var writer = new BinaryWriter(fs);
                writer.Write(files.Length);

                for (int i = 0; i < files.Length; i++)
                {
                    char[] fileName = Path.GetFileName(files[i]).ToCharArray();
                    writer.Write(fileName.Length);
                    writer.Write(fileName);

                    byte[] buffer = File.ReadAllBytes(files[i]);
                    writer.Write(buffer.Length);
                    writer.Write(buffer);
                }

                byte[] data = CompressEx.CompressBytes(fs.ToArray());
                File.WriteAllBytes(@"E:\temp\License2.dll", data);
            }

            //@"E:\temp\License.dll", FileMode.CreateNew, FileAccess.Write
        }

        private static void Dec()
        {
            //byte[] datas = File.ReadAllBytes(@"E:\temp\dic\D3");
            //byte[] data2 = CompressEx.CompressBytes(datas);
            //byte[] data3 = CompressEx.DecompressBytes(data2);
            //File.WriteAllBytes(@"E:\temp\dic\D3_2", data3);

            byte[] buffer = CompressEx.DecompressBytes(File.ReadAllBytes(@"E:\temp\License2.dll"));

            using (var fs = new MemoryStream(buffer))
            {
                var reader = new BinaryReader(fs);
                int count = reader.ReadInt32();
                for (int i = 0; i < count; i++)
                {
                    int len = reader.ReadInt32();
                    string fileName = new string(reader.ReadChars(len));

                    len = reader.ReadInt32();
                    byte[] data = reader.ReadBytes(len);

                    string filePath = PathEx.Combine(PathType.Local, @"E:\temp\dic2", fileName);
                    File.WriteAllBytes(filePath, data);
                }
            }
        }


        private static void TestMemoryPool()
        {
            //var pool = MemoryPool<int>.Shared;
            //using (IMemoryOwner<int> blockOwner = pool.Rent(1000))
            //{
            //    Memory<int> block = blockOwner.Memory;

            //    Memory<int> block2 = new Memory<int>();

            //    ReadOnlySpan<char> str = "sfaf".AsSpan();
            //}
        }

        private static void Tcp()
        {
            EndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.10.96"), 16001);
            int count = 20;
            List<Socket> clients = new List<Socket>();
            for (int j = 0; j < 10; j++)
            {
                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(500);
                    var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    client.Connect(endPoint);
                    clients.Add(client);
                }

                Thread.Sleep(2000);
                foreach (var client in clients)
                {
                    client.Disconnect(false);
                    client.Dispose();
                    Thread.Sleep(1000);
                }
                clients.Clear();
            }
        }


        private static void Test()
        {
            //Socket client = new Socket( SocketType.Dgram, ProtocolType.Udp);
            //client.Poll(System.Threading.Timeout.Infinite, SelectMode.SelectRead);


            //using (var pointer = new UnmanagedMemoryPointer<byte>(NetHelper.MTU_MAX))
            //{
            //    Span<byte> span = pointer.GetSpan();
            //    Socket socket = new Socket(null);
            //    int len = socket.Receive(span);

            //    EndPoint endPoint = null;
            //    int leng2 = socket.ReceiveFrom(span, ref endPoint);
            //}
        }

        //private static void TestSpan(in ReadOnlySpan<int> span)
        //{
        //    span[0] = 123;
        //}


        //private static void TestPtrCopyPtr()
        //{
        //    byte[] srcBuffer = new byte[4] { 1, 2, 3, 4 };
        //    byte[] destBuffer = new byte[4];


        //    fixed (byte* src = srcBuffer)
        //    {
        //        fixed (byte* dest = destBuffer)
        //        {
        //            Marshal.Copy();
        //            Buffer.MemoryCopy(src, dest, destBuffer.Length, srcBuffer.Length);
        //        }
        //    }
        //}

        private static void TestConcurrentBag()
        {
            ConcurrentBag<int> items = new ConcurrentBag<int>();
            int value;
            if (items.TryTake(out value))
            {

            }
            else
            {

            }

            items.Add(1);
            items.Add(2);
            items.Add(3);

            if (items.TryTake(out value))
            {

            }
            else
            {

            }

            IEnumerable<int> ret1 = items.Take(1);
            IEnumerable<int> ret2 = items.Take(10);
        }


        private static void TestCode1()
        {
            IPGlobalProperties computerCroperties = IPGlobalProperties.GetIPGlobalProperties();
            TcpConnectionInformation[] tcpConnections = computerCroperties.GetActiveTcpConnections();
            IPEndPoint[] tcpListeners = computerCroperties.GetActiveTcpListeners();


            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
            foreach (NetworkInterface adapter in nics)
            {
                IPv4InterfaceStatistics ipv4Statistics = adapter.GetIPv4Statistics();
                var rcvMB = ipv4Statistics.BytesReceived / 1024 / 1024;
                var sendMB = ipv4Statistics.BytesSent / 1024 / 1024;
            }


        }
        private static void TestLog()
        {
            //LoadConfigFromResource();
            Exception exception = new Exception("这是一个异常.");
            //for (int i = 0; i < 20; i++)
            //{
            //    Console.WriteLine($"第:{i + 1}");

            //    for (int j = 0; j < 10000; j++)
            //    {


            ZLoger.Trace("ZLoger.Trace");
            ZLoger.Debug("ZLoger.Debug");
            ZLoger.Info("ZLoger.Info");
            ZLoger.Warn("ZLoger.Warn");
            ZLoger.Error("ZLoger.Error");
            ZLoger.Fatal("ZLoger.Fatal");

            Loger.Trace("Trace");
            Loger.Debug("Debug");
            Loger.Info("Info");
            Loger.Warn("Warn");
            Loger.Error("Error");
            Loger.Fatal("Fatal");

            Loger.Trace(exception, "Trace");
            Loger.Debug(exception, "Debug");
            Loger.Info(exception, "Info");
            Loger.Warn(exception, "Warn");
            Loger.Error(exception, "Error");
            Loger.Fatal(exception, "Fatal");
            //    }
            //}

            //Console.WriteLine($"Count:{LogItem.Count}");
        }
        private static bool LoadConfigFromResource()
        {
            try
            {
                var entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                if (entryAssembly == null)
                {
                    return false;
                }

                //var rm = new System.Resources.ResourceManager(LogConstant.DEFAULT_CONFIG_FILE_NAME, entryAssembly);
                //var str = rm.GetString(LogConstant.DEFAULT_CONFIG_FILE_NAME);
                string[] manifestResourceNames = entryAssembly.GetManifestResourceNames();
                if (!manifestResourceNames.Contains(LogConstant.DEFAULT_CONFIG_FILE_NAME))
                {
                    return false;
                }

                using (var stream = entryAssembly.GetManifestResourceStream(LogConstant.DEFAULT_CONFIG_FILE_NAME))
                {
                    if (stream == null)
                    {
                        return false;
                    }

                    byte[] buffer = new byte[stream.Length];
                    int readLenth = stream.Read(buffer, 0, buffer.Length);

                    bool flag = false;
                    string xmlStr = Encoding.UTF8.GetString(buffer);
                    while (true)
                    {
                        try
                        {
                            var xdoc = XDocument.Parse(xmlStr);
                            Loger.LoadConfig(xdoc);
                        }
                        catch (Exception exi)
                        {
                            LogSysInnerLog.OnRaiseLog($"从程序集资源里查找配置并加载日志配置异常", exi);
                            if (flag)
                            {
                                break;
                            }

                            xmlStr = Encoding.Default.GetString(buffer);
                            flag = true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogSysInnerLog.OnRaiseLog("从程序集资源里查找配置异常", ex);
            }

            return false;
        }

        private static void InitLog()
        {
            ZLoger.OutputOption = ZLogerOutputOptions.Loger;
            var redirectAppenderToUI = (RedirectAppender)Loger.GetAppenderByName(null, "RedirectToUI");
            if (redirectAppenderToUI != null)
            {
                redirectAppenderToUI.RedirectOuput += RedirectLogOutput;
            }
        }

        private static void RedirectLogOutput(object sender, RedirectOuputArgs e)
        {
            ConsoleColor fontColor;
            string str;
            try
            {
                var item = e.Item;
                str = string.Format("{0} {1}", e.Item.Time.ToString(LogConstant.DateTimeFormat), e.Item.Content);

                switch (item.Level)
                {
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Trace:
                        fontColor = ConsoleColor.Gray;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Debug:
                        fontColor = ConsoleColor.Gray;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Info:
                        fontColor = ConsoleColor.White;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Warn:
                        fontColor = ConsoleColor.Yellow;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Error:
                        fontColor = ConsoleColor.Red;
                        break;
                    case UtilZ.Dotnet.Ex.Log.LogLevel.Fatal:
                        fontColor = ConsoleColor.Red;
                        break;
                    default:
                        return;
                }
            }
            catch (Exception ex)
            {
                fontColor = ConsoleColor.Red;
                str = ex.Message;
            }

            var oldForegroundColor = Console.ForegroundColor;
            Console.ForegroundColor = fontColor;
            Console.WriteLine(str);
            Console.ForegroundColor = oldForegroundColor;
        }
    }
}
